<?php
/**
 * The MIT License
 *
 * Copyright (c) <year> <copyright holders>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 *
 * @author Damiano Ciarla
 * @package plugin
 * @subpackage log/class/db
 */
class Log_Db_BxdDatabase extends Log_Abstract_DbGenUtils implements Log_Interface_Connection
{
	/**
	 * Istanza della classe BXDDb contenente tutti i metodi per l'esecuzione delle query
	 *
	 * @var BXDDb
	 */
	private $_db;

	/**
	 * Istanza contenente la configurazione del database
	 *
	 * @var BXDDbConfig
	 */
	private $_dbConf;

	/**
	 * Nome della tabella degli errori
	 *
	 * @var string
	 */
	private $_tableError;

	/**
	 * Nome della tabella delle eccezioni
	 *
	 * @var string
	 */
	private $_tableException;

	public function __construct($host = null, $username = null, $password = null, $dbname = null)
	{
		Bxd::includeLib()->db();

		// Verifico se sono stati passati parametri di connessione
		if($host === null && $username === null && $password === null && $dbname === null)
		{
			// Nessun parametro impostato e recupero la connessione principale
			$this->_db = BXDDb::getInstance();
		}
		else
		{
			Bxd::includeLib()->dbConfig();

			// Creo una nuova configurazione custom per la connessione al database
			$dbConf = new BXDDbConfig();
			$dbConf->connectionName	= "plugin_log";
			$dbConf->host = $host;
			$dbConf->username = $username;
			$dbConf->passwd = $password;
			$dbConf->dbname = $dbname;
			$dbConf->type = "mysql";
			$dbConf->persistent = false;
			$dbConf->collate = "utf8_unicode_ci";
			$dbConf->charset = "utf8";

			$this->_dbConf = $dbConf;

			$this->_db = BXDDb::getInstance();
			// Aggiungo la connessione a eventuali connessioni presenti
			$this->_db->addConnect($dbConf);
			// Eseguo la connessione
			$this->_db->connect($this->_dbConf->connectionName);
		}
	}


	public function checkTable($tableError, $tableException)
	{
		if ($this->_dbConf !== null)
			$this->_db->useConnection($this->_dbConf->connectionName);

		$this->_tableError = $tableError;
		$this->_tableException = $tableException;

		$checkError = false;
		$checkException = false;

		// Recupero tutte le tabelle presenti nel database
		$result = $this->_db->execute("SHOW TABLES")->fetchAll(PDO::FETCH_COLUMN);

		foreach($result as $row)
		{
			// Verifico se la tabella degli errori è già stata creata
			if($row == $tableError)
				$checkError = true;

			// Verifico se la tabella delle eccezioni è già stata creata
			if($row == $tableException)
				$checkException = true;
		}

		// Se la tabella degli errori non è stata creata la creo
		if(!$checkError)
		{
			$sql = "
			CREATE TABLE `" . $tableError . "` (
				`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
				`errno` int(10) unsigned DEFAULT NULL,
				`errtype` text COLLATE utf8_unicode_ci,
				`errstr` text COLLATE utf8_unicode_ci,
				`errfile` text COLLATE utf8_unicode_ci,
				`errline` int(10) unsigned DEFAULT NULL,
				`errcontext` text COLLATE utf8_unicode_ci,
				`client_url` text COLLATE utf8_unicode_ci,
				`client_ip` varchar(45) COLLATE utf8_unicode_ci DEFAULT NULL,
				`date_added` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
				PRIMARY KEY (`id`)
			) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
			";

			$this->_db->execute($sql);
		}

		// Se la tabella delle eccezioni non è stata creata la creo
		if(!$checkException)
		{
			$sql = "
			CREATE TABLE `" . $tableException . "` (
				`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
				`message` text COLLATE utf8_unicode_ci,
				`previus` text COLLATE utf8_unicode_ci,
				`code` int(10) unsigned DEFAULT NULL,
				`file` text COLLATE utf8_unicode_ci,
				`line` int(10) unsigned DEFAULT NULL,
				`trace` text COLLATE utf8_unicode_ci,
				`trace_as_string` text COLLATE utf8_unicode_ci,
				`client_url` text COLLATE utf8_unicode_ci,
				`client_ip` varchar(45) COLLATE utf8_unicode_ci DEFAULT NULL,
				`date_added` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
				PRIMARY KEY (`id`)
			) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
			";

			$this->_db->execute($sql);
		}
	}

	/**
	 * Metodo che memorizza l'errore che viene intercettato
	 *
	 * @param int $errno Numero identificativo della tipologia dell'errore
	 * @param string $errstr Descrizione
	 * @param string $errfile File dove si è verificato l'errore
	 * @param int $errline Line dove si è verificato l'errore
	 * @param string $errcontext Valori aggiuntivi
	 */
	public function storeError($errno = null, $errstr = null, $errfile = null, $errline = null, $errcontext = null)
	{
		$sql = "
		INSERT INTO `" . $this->_tableError . "` SET
		`errno` = ?,
		`errtype` = ?,
		`errstr` = ?,
		`errfile` = ?,
		`errline` = ?,
		`errcontext` = ?,
		`client_url` = ?,
		`client_ip` = ?";

		if ($this->_dbConf !== null)
			$this->_db->useConnection($this->_dbConf->connectionName);

		$errtype = $this->_error2string($errno);

		Bxd::includeLib()->httpUtils();
		$client_url = bxd\lib\http\Utils::realUrl();
		$client_ip = bxd\lib\http\Utils::realIp();

		$this->_db->execute($sql, array(
			(($errno == null) ? null : $errno),
			(($errtype == null) ? null : $errtype),
			(($errstr == null) ? null : $errstr),
			(($errfile == null) ? null : $errfile),
			(($errline == null) ? null : $errline),
			(($errcontext == null) ? null : print_r($errcontext, true)),
			(($client_url == null) ? null : $client_url),
			(($client_ip == null) ? null : $client_ip)
		));
	}

	/**
	 * Meotodo che memorizza l'eccezione catturata
	 *
	 * @param Exception $e Istanza della classe Exception
	 */
	public function storeException(Exception $e)
	{
		$sql = "
		INSERT INTO `" . $this->_tableException . "` SET
		`message` = ?,
		`previus` = ?,
		`code` = ?,
		`file` = ?,
		`line` = ?,
		`trace` = ?,
		`trace_as_string` = ?,
		`client_url` = ?,
		`client_ip` = ?";

		if ($this->_dbConf !== null)
			$this->_db->useConnection($this->_dbConf->connectionName);

		Bxd::includeLib()->httpUtils();
		$client_url = bxd\lib\http\Utils::realUrl();
		$client_ip = bxd\lib\http\Utils::realIp();

		$this->_db->execute($sql, array(
			(($e->getMessage() == null) ? null : $e->getMessage()),
			(($e->getPrevious() == null) ? null : $e->getPrevious()),
			(($e->getCode() == null) ? null : $e->getCode()),
			(($e->getFile() == null) ? null : $e->getFile()),
			(($e->getLine() == null) ? null : $e->getLine()),
			(($e->getTrace() == null) ? null : print_r($e->getTrace(), true)),
			(($e->getTraceAsString() == null) ? null : $e->getTraceAsString()),
			(($client_url == null) ? null : $client_url),
			(($client_ip == null) ? null : $client_ip)
		));
	}

	public function countError($type = null)
	{
		$sql = "
		SELECT COUNT(*) tot_result
		FROM `" . $this->_tableError . "`
		WHERE 1
		" . (($type !== null) ? "AND `errtype` = :errtype" : "");

		$prepare = $this->_db->prepare($sql);

		if($type !== null)
			$prepare->bindParam("errtype", $type, PDO::PARAM_STR);

		$result = $prepare->execute();

		$data = $result->fetch(PDO::FETCH_ASSOC);
		return $data['tot_result'];
	}

	public function getError($page = 1, $limit = 30, $type = null)
	{
		$sql = "
		SELECT *
		FROM `" . $this->_tableError . "`
		WHERE 1
		" . (($type !== null) ? "AND `errtype` = :errtype" : "") . "
		ORDER BY id DESC
		LIMIT " . (($page - 1) * $limit) . ", " . $limit;

		$prepare = $this->_db->prepare($sql);

		if($type !== null)
			$prepare->bindParam("errtype", $type, PDO::PARAM_STR);

		$result = $prepare->execute();

		return $result->fetchAll(PDO::FETCH_ASSOC);
	}

	public function getUniqueTypeError()
	{
		$sql = "
		SELECT `errtype`
		FROM `" . $this->_tableError . "`
		GROUP BY `errtype`
		";

		$result = $this->_db->execute($sql);

		return $result->fetchAll(PDO::FETCH_ASSOC);
	}

	public function countException()
	{
		$sql = "
		SELECT COUNT(*) tot_result
		FROM `" . $this->_tableException . "`
		";

		$result = $this->_db->execute($sql);

		$data = $result->fetch(PDO::FETCH_ASSOC);
		return $data['tot_result'];
	}

	public function getException($page = 1, $limit = 30)
	{
		$sql = "
		SELECT *
		FROM `" . $this->_tableException . "`
		ORDER BY id DESC
		LIMIT " . (($page - 1) * $limit) . ", " . $limit;

		$result = $this->_db->execute($sql);

		return $result->fetchAll(PDO::FETCH_ASSOC);
	}

	public function closeConnection()
	{
		$this->_db->close((($this->_dbConf !== null) ? $this->_dbConf->connectionName : null));
	}
}
?>